#pragma once

#define WIN32_LEAN_AND_MEAN
#define DIRECTINPUT_VERSION 0x0800
#include <windows.h>
#include <dinput.h>

#include <vector>
#include "DiolDevice.h"

namespace Diol
{

class DeviceEnumerationTrigger;
	
/*
	DeviceManager

	The DeviceManager object is responsible for maintaining a list of 
	the Devices that are currently connected to the computer.

	It is possible to register listeners the manager so client code can be 
	called whenever a Device is plugged in or removed.
*/
class DeviceManager
{
public:
	typedef std::vector<std::pair<DeviceInstance, Device*>> DeviceList;
	
	DeviceManager( bool ignoreXInputControllers, bool consoleApplication /*, HWND windowHandle*/ );
	virtual ~DeviceManager();

	virtual void				update();
	void						updateDeviceList();

	class Listener
	{
	public:
		virtual void onDeviceConnected( DeviceManager* /*deviceManager*/, Device* /*device*/ ) {}
		virtual void onDeviceDisconnecting( DeviceManager* /*deviceManager*/, Device* /*device*/ ) {}
	};

	void						addListener( Listener* listener );
	bool						removeListener( Listener* listener );
	void						removeListeners();
	
	const DeviceList&			getDevices() const		{ return mDevices; }
	Device*						getDeviceByName( const std::string& name ) const;

private:
	void						createDirectInput();
	void						deleteDirectInput();
	
	
	void						addDevice( const DeviceInstance& identifier );
	void						removeDevice( const DeviceInstance& identifier );

	static BOOL	CALLBACK		enumDevicesCallback( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef );
	static void					deviceListToDeviceIdentifiers( const DeviceList& list, DeviceIdentifiers& identifiers );
	static void					calculateAddedDevicesList( const DeviceIdentifiers& previousDevices, const DeviceIdentifiers& currentDevices, DeviceIdentifiers& addedDevices );
	static void					calculateRemovedDevicesList( const DeviceIdentifiers& previousDevices, const DeviceIdentifiers& currentDevices, DeviceIdentifiers& addedRemoved );
	
	bool						mIgnoreXInputControllers;
	DeviceEnumerationTrigger*	mEnumerationTrigger;
	static IDirectInput8*		mDirectInput;
	//HWND						mWindowHandle;
	DeviceList					mDevices;

	// Listeners
	typedef						std::vector<Listener*> Listeners; 
	Listeners					mListeners;
};

}